#pragma once
#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include <unistd.h>
#include <signal.h>
#include <jsoncpp/json/json.h>
#include "Compiler.hpp"
#include "Run.hpp"
#include "../Common/Log.hpp"
namespace ns_compilerRun
{
    using namespace ns_compilier;
    using namespace ns_runner;
    using namespace ns_log;
    class Complie_Run
    {
    public:
        // 删除临时文件
        static void RemoveTempFile(const std::string &filename)
        {
            std::string temp_src = FileTool::FileSplice::SpliceSrcPathName(filename);
            if (FileTool::FileIsExists::IsFileExists(temp_src))
                unlink(temp_src.c_str());
            std::string stderror_Compiler = FileTool::FileSplice::SpliceCompileStderrLog(filename);
            if (FileTool::FileIsExists::IsFileExists(stderror_Compiler))
                unlink(stderror_Compiler.c_str());
            //删除exe文件
            std::string exe_tempfile = FileTool::FileSplice::SpliceExePathName(filename);
            if(FileTool::FileIsExists::IsFileExists(exe_tempfile))
                unlink(exe_tempfile.c_str());
            //删除stdin、stdout、stderr日志临时文件
            std::string stdin_tempfile =  FileTool::FileSplice::SpliceRunStdin(filename);
            if(FileTool::FileIsExists::IsFileExists(stdin_tempfile))
                unlink(stdin_tempfile.c_str());
            std::string stdout_tempfile =  FileTool::FileSplice::SpliceRunStdout(filename);
            if(FileTool::FileIsExists::IsFileExists(stdout_tempfile))
                unlink(stdout_tempfile.c_str());
            std::string stderr_tempfile =  FileTool::FileSplice::SpliceRunStderr(filename);
            if(FileTool::FileIsExists::IsFileExists(stderr_tempfile))
                unlink(stderr_tempfile.c_str());
        }
        static std::string GetReasonStr(int code, const std::string &filename)
        {
            std::string desc;
            switch (code)
            {
            case 0:
                desc = "运行成功";
                break;
            case -1:
                desc = "用户提交的代码为空";
                break;
            case -2:
                desc = "未知错误";
                break;
            case -3:
                RWFile::ReadDataToFile(FileTool::FileSplice::SpliceCompileStderrLog(filename), &desc, true);
                break;
            case SIGABRT:
                desc = "内存超限";
                break;
            case SIGXCPU:
                desc = "运行超时";
                break;
            case SIGSEGV:
                desc = "段错误";
                break;
            case SIGFPE:
                desc = "浮点数溢出";
                break;
                // TODO--这里后期可以添加新的case
            default:
                desc = "未知错误,code: " + std::to_string(code);
                break;
            }
            return desc;
        }
        static bool Start(const std::string &in_json, std::string *outjsonstr)
        {
            /*---提交：{code : "xxx" , inout : "自定义测试用例",}*/
            // 反序列化
            Json::Value root; // 存放in_json的反序列化后的信息
            Json::CharReaderBuilder build;
            build["emitUTF8"] = true; // 设置编码集
            std::unique_ptr<Json::CharReader> read(build.newCharReader());
            std::string strerror;
            read->parse(in_json.c_str(), in_json.c_str() + in_json.size(), &root, &strerror);
            std::string code = root["code"].asString();
            std::string input = root["input"].asString();
            int cpu_time_limit = root["cpu_limit"].asInt(); // 获取来自题目中的运行时间限制--1s
            int mem_limit = root["mem_limit"].asInt();      // 获取来自题目中的内存限制
            Json::Value value;
            int status_result = 0;     // 退出码
            std::string uniq_filename; // 唯一的文件名
            int rescode = 0;           // 运行结果
            if (code.size() == 0)
            {
                status_result = -1;
                goto END;
            }
            // 毫米级时间戳 + 原子性递增 --确保文件名唯一
            uniq_filename = UniqueFileName::SetUniqueFileName();
            // 将数据写入文件
            if (!RWFile::WriteDataToFile(FileSplice::SpliceSrcPathName(uniq_filename), code))
            {
                status_result = -2;
                goto END;
            }
            // 编译
            if (!Compilier::CompilierFunc(uniq_filename))
            {
                status_result = -3; // 编译错误返回错误码-3，上层进行解析
                goto END;
            }
            // 运行
            rescode = Run::Running(uniq_filename, cpu_time_limit, mem_limit);
            if (rescode < 0)
            {
                status_result = -4; // 运行模块不关心运行的结果是什么，设置退出码-4
            }
            else if (rescode > 0)
            {
                status_result = rescode;
            }
            else
            {
                // 运行成功
                status_result = 0;
            }
        END:
            // 统一处理错误
            value["status"] = status_result;
            value["reason"] = GetReasonStr(status_result, uniq_filename);
            if (status_result == 0)
            {
                std::string stdout_str, stderr_str;
                RWFile::ReadDataToFile(FileSplice::SpliceRunStdout(uniq_filename), &stdout_str, true);
                RWFile::ReadDataToFile(FileSplice::SpliceRunStderr(uniq_filename), &stderr_str, true);
                value["stdout"] = stdout_str;
                value["stderr"] = stderr_str;
            }

            // 序列化
            Json::StreamWriterBuilder build_wr;
            build_wr["emitUTF8"] = true;
            std::unique_ptr<Json::StreamWriter> wr(build_wr.newStreamWriter());
            std::stringstream ss;
            wr->write(value, &ss);
            *outjsonstr = ss.str();

            // 删除临时文件
            RemoveTempFile(uniq_filename);
            return true;
        }
    };
}